//Copyright (C) 2011 Ron Coleman. Contact: ronncoleman@gmail.com
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 3 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

package org.workplicity.cia.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import org.workplicity.cia.worklet.ElogsWorklet;
import org.workplicity.elog.entry.ElogUser;
import org.workplicity.elog.entry.ElogUser.Function;
import org.workplicity.elog.entry.Trade;
import org.workplicity.entry.Entry;
import org.workplicity.entry.User;
import org.workplicity.util.Helper;
import org.workplicity.util.WorkDate;
import org.workplicity.worklet.WorkletContext;

/**
 * This helper class does various convenience functions.
 * @author Ron Coleman
 */
public class CIAHelper {
    /**
     * Default age == 1 week
     */
    public static final Integer AGE_DEFAULT = 2;

    /**
     * Returns true if the work date is more recent than the user stamp.
     * @param date Date
     * @return True if work date is more recent, false otherwise
     */
    public static boolean isRecent(WorkDate date) {
        WorkDate stamp = Helper.whoAmI(WorkletContext.getInstance()).getStamp();

        if(stamp == null || date == null)
            return true;

        if(stamp.getTime() < date.getTime())
            return true;

        return false;
    }

    /**
     * Returns true if the entry is more recent than the user stamp.
     * @param entry entry
     * @return True if work date is more recent, false otherwise
     */
    public static boolean isRecent(Entry entry) {
        return isRecent(entry.getUpdateDate());
    }

    /**
     * This method gathers the subordinates recursively.
     * @param target Target user
     * @param set List compiled so far
     */
    public static void gatherSubordinates(ElogUser target,HashSet<ElogUser> set) {
        // If user has no subordinates, then this is the user set
        if (target.getFunction() == Function.WORKER)
            return;

        // Otherwise gather the users that are subordinates of
        // the prime user
        ArrayList<User> users = ElogsWorklet.getInstance().getUsersCache().getCache();

        Integer primeUserId = target.getId();

        for (User user : users) {
            ElogUser elogUser = (ElogUser) user;

            Integer bossId = elogUser.getBossId();
            if (bossId != -1 && bossId.equals(primeUserId)) {
                set.add(elogUser);

                // If this prime user is an exec, then it
                // only supers can point to it...so we'll need
                // to get the supervisor's subordinates
                if (isManagement(target)) {
                    gatherSubordinates(elogUser, set);
                }
            }
        }
    }

    /**
     * Returns true if this user is a management type.
     * @param target Target user
     * @return True of the user is in management, false otherwise
     */
    public static boolean isManagement(ElogUser target) {
        Function function = target.getFunction();

        if(function == Function.MANAGER || function == Function.SUPERVISOR ||
                function == Function.DIRECTOR || function == Function.PRESIDENT)
            return true;

        return false;
    }

    /**
     * This method gathers the users with the target trade.
     * @param target Target user
     * @param list List compiled so far
     */
    public static void gatherUsers(Trade target,HashSet<ElogUser> set) {
        ArrayList<User> users = ElogsWorklet.getInstance().getUsersCache().getCache();

        for(User user : users) {
            ElogUser auser = (ElogUser)user;

            for(Integer id : auser.getTradeList()) {
                if(target.getId().equals(id)) {
                    set.add(auser);
                    break;
                }
            }
        }
    }

//    /**
//     * Retrieves all the trades.
//     * TODO: should be cached like users.
//     * @return Trades
//     */
//    public static ArrayList<Trade> getTrades() {
//        WorkletContext context =
//                ElogsWorklet.getInstance().getContext();
//
//        ArrayList<Trade> trades =
//                Helper.query("/ list [ title = 'Trades' ] / list ", context);
//
//        return trades;
//    }

    /**
     * Gets the string as a one-liner.
     * @param s String
     * @return String
     */
    public static String asOneLine(String s) {
        int j = s.indexOf('\n');

        if(j == -1)
            return s;

        return s.substring(0, j);
    }

    /**
     * Converts a trade id to a trade.
     * @param id
     * @return
     */
    public static Trade toTrade(Integer id) {
        ArrayList<Trade> trades = ElogsWorklet.getInstance().getTrades().getCache();

        for(Trade trade : trades) {
            if(trade.getId().equals(id))
                return trade;
        }

        return null;
    }

    /**
     * Gets the trade of a user -- the first one that is listed.
     * @param user User
     * @return
     */
    public static Trade toTrade(ElogUser user) {
        if(user.getTradeList().isEmpty())
            return null;

        ArrayList<Trade> trades = ElogsWorklet.getInstance().getTrades().getCache();
        
        for(Integer id : user.getTradeList()) {
            for(Trade trade : trades) {
                if(id.equals(trade.getId()))
                    return trade;
            }
        }

        return null;
    }

    /**
     * Converts a user id to a user.
     * @param id User id
     * @return User
     */
    public static ElogUser toUser(Integer id) {
        ElogsWorklet.getInstance().getUsersCache().refresh();

        ArrayList<User> users =
                ElogsWorklet.getInstance().getUsersCache().getCache();

        for(User user : users)
            if(user.getId().equals(id))
                return (ElogUser) user;

        return null;
    }

    /**
     * Converts a user id to a user.
     * @param id User id
     * @param users Existing users (perhaps sorted?)
     * @return User
     */
    public static ElogUser toUser(Integer id,ArrayList<User> users) {
        for(User user : users)
            if(user.getId().equals(id))
                return (ElogUser) user;

        return null;
    }


    /**
     * Converts an elog title to a user name
     * @param elogTitle Elog title
     * @return Elog user
     */
    public static ElogUser toUser(String elogTitle) {
        ArrayList<User> users =
                ElogsWorklet.getInstance().getUsersCache().getCache();

        for(User user : users) {
            ElogUser euser = (ElogUser) user;

            if(euser.getReposTitle().equals(elogTitle))
                return euser;
        }

        return null;
    }

    public final static String[] AGES = {
        "<= 24 hours",
        "<= 48 hours",
        "<= 1 week",
        "<= 30 days",
        "> 30 & <= 60 days",
        "> 60 & <= 90 days",
        "> 90 & <= 180 days",
        "> 180 & <= 365 days",
        "> 1 year"
    };

    public static HashMap<String,Pair<Long,Long>> getAgeMap() {
        Calendar cal = Calendar.getInstance();

        cal.add(Calendar.HOUR, -24);
        long twentyFour = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, -48);
        long fortyEight = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, -7 * 24);
        long oneWeek = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -1);
        final long oneMonth = cal.getTimeInMillis();


        cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -2);
        final long twoMonths = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -3);
        final long threeMonths = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -6);
        final long sixMonths = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -12);
        final long oneYear = cal.getTimeInMillis();

        cal = Calendar.getInstance();
        cal.add(Calendar.YEAR, -25);
        final long forever = cal.getTimeInMillis();


        
        long[] starts = {
            twentyFour,
            fortyEight,
            oneWeek,
            oneMonth,
            threeMonths,
            sixMonths,
            oneYear,
            forever
        };

        long now = System.currentTimeMillis();
        long[] ends = {
            now,
            now,
            now,
            now,
            twoMonths,
            threeMonths,
            sixMonths,
            oneYear
        };

        HashMap map = new HashMap<String,Pair<Long,Long>>( );
        for(int i=0; i < starts.length; i++)
            map.put(AGES[i], new Pair<Long,Long>(starts[i],ends[i]));

        return map;
    }
}
